package com.hu.network.threadpool;

import android.util.LruCache;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.hu.network.task.AbstractTask;
import com.hu.network.task.exception.TaskException;
import timber.log.Timber;

/**
 * 说明：
 *
 * @author ： hucanhua
 * @date ： 2017/10/25
 */
public class ThreadPoolUtil {

    private static ThreadPoolUtil mThreadPoolUtil = null;
    private ExecutorService mExecutorService;
    private LruCache<String, Future> mTaskContent;

    private ThreadPoolUtil(Builder builder) {
        this.mTaskContent = new LruCache<>(20);
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("flightmanage-executorService-%d").build();
        this.mExecutorService = new ThreadPoolExecutor(builder.mCorePoolSize, builder.mMaximumPoolSize, builder.mKeepAliveTime, builder.mTimeUnit, new ArrayBlockingQueue<Runnable>(100), namedThreadFactory);
        if (builder.mAwaitTerminationTime > 0L) {
            try {
                this.mExecutorService.awaitTermination(builder.mAwaitTerminationTime, builder.mTimeUnit);
            } catch (InterruptedException var4) {
                Timber.d("mAwaitTerminationTime 线程超时或被中断");
            }
        }
    }

    public static ThreadPoolUtil getInstance() {
        if (mThreadPoolUtil == null) {
            synchronized (ThreadPoolUtil.class) {
                if (mThreadPoolUtil == null) {
                    mThreadPoolUtil = new Builder().build();
                }
            }
        }
        return mThreadPoolUtil;
    }

    public <T> Future<T> excute(AbstractTask<T> callable) {
        Future<T> future = mExecutorService.submit(callable);
        this.mTaskContent.put(callable.getUuid(), future);
        return future;
    }

    public void cancel(String uuid) throws TaskException {
        cancel(mTaskContent.get(uuid));
    }

    public <V> void cancel(Future<V> future) throws TaskException {
        try {
            if (future != null) {
                if (future.isDone()) {
                    Timber.e("任务%s已经完成，不能取消.任务执行结果为==>>");
                    return;
                }

                future.cancel(true);
                Timber.d("任务%s已取消");
            } else {
                Timber.e("任务%s未添加执行或已移除...");
            }

        } catch (Exception var3) {
            throw new TaskException(var3);
        }
    }

    public static class Builder {
        private int mCorePoolSize = 3;
        private int mMaximumPoolSize = 30;
        private TimeUnit mTimeUnit = TimeUnit.SECONDS;
        private long mKeepAliveTime = 120L;
        private long mAwaitTerminationTime = 0L;


        public ThreadPoolUtil.Builder setCorePoolSize(int corePoolSize) {
            this.mCorePoolSize = corePoolSize;
            return this;
        }

        public ThreadPoolUtil.Builder setMaximumPoolSize(int maximumPoolSize) {
            this.mMaximumPoolSize = maximumPoolSize;
            return this;
        }

        public ThreadPoolUtil.Builder setKeepAliveTime(long keepAliveTime) {
            this.mKeepAliveTime = keepAliveTime;
            return this;
        }

        public ThreadPoolUtil.Builder setTimeUnit(TimeUnit timeUnit) {
            this.mTimeUnit = timeUnit;
            return this;
        }

        public ThreadPoolUtil.Builder setAwaitTerminationTime(long awaitTerminationTime) {
            this.mAwaitTerminationTime = awaitTerminationTime;
            return this;
        }

        public ThreadPoolUtil build() {
            ThreadPoolUtil.mThreadPoolUtil = new ThreadPoolUtil(this);
            return ThreadPoolUtil.mThreadPoolUtil;
        }
    }
}
